package us.gaaoc.framework.webapp.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;

import org.apache.myfaces.custom.fileupload.UploadedFile;
import org.hibernate.Hibernate;
import org.pdfbox.pdmodel.PDDocument;

import us.gaaoc.framework.dao.ModelFacade;
import us.gaaoc.framework.model.CaseRecord;
import us.gaaoc.framework.model.Court;
import us.gaaoc.framework.model.DocPageRange;
import us.gaaoc.framework.model.DocumentInstance;
import us.gaaoc.framework.model.DocumentPackage;
import us.gaaoc.framework.model.DocumentStatus;
import us.gaaoc.framework.model.Documents;
import us.gaaoc.framework.model.LocalCaseFilingType;
import us.gaaoc.framework.model.Person;
import us.gaaoc.framework.model.PersonParticipants;
import us.gaaoc.framework.model.constants.Constants;
import us.gaaoc.framework.util.DateUtil;
import us.gaaoc.framework.util.io.FileUtility;
import us.gaaoc.framework.util.pdf.Concatenate;
import us.gaaoc.framework.util.pdf.PageRangesFromTextTargetsUtility;
import us.gaaoc.framework.util.pdf.SplitPDF;

public class UploadPackageUtility {

	public static void uploadPackage(
			Court court, 
			String caseRecordUuid,
			UploadedFile packageDoc, 
			DocumentPackage docPackage, 
			Person person,
			List<Documents> uploadDocumentList,
			ModelFacade mf
	) throws UploadPackageException, Exception
	{

		if (caseRecordUuid != null  && (packageDoc != null)) 
		{ 
			byte[] fileBytes = (byte[]) packageDoc.getBytes();
			
			File newFile = File.createTempFile(packageDoc.getName(), 
					".pdf",
					new File("C:" + File.separator + "temp" + File.separator));
			FileOutputStream fw = new FileOutputStream(newFile);
			fw.write(fileBytes);
			fw.flush();
			fw.close();

			Person personSigned = person;
		
			UploadPackageUtility.concatExhibits(docPackage, newFile, uploadDocumentList, court);

			splitPDFPackage(docPackage, newFile, caseRecordUuid,
					personSigned,mf,court);

			List<DocPageRange> dprList = mf.findAllPageRangeByPackageUuid(docPackage);
			
			CaseRecord cr = mf.findCaseRecordById(caseRecordUuid,court.getUuid());
			
			for(DocPageRange dpr : dprList)
			{
				DocumentInstance documentInstance = dpr.getDocumentInstance();
				// This is for revmods
				if(
				(	documentInstance.getDocumentType().getCode() == Constants.DocumentType.REVIEW_MODIFICATION ||
					docPackage.getCaseRecordAction().getId() == 3) && 
					cr.getCourt().getUuid().equals("courtUuidClarke"))						
				{
					
					// move witness to defendent			
					for(PersonParticipants pp : cr.getPersonParticipants())
					{
						if(pp.getRelationship().getCode() == Constants.ParticipantRelationship.Witness)
						{
							pp.setRelationship(
									mf.findParticipantRelationship(Constants.ParticipantRelationship.DefendantParty));
							mf.addCaseRecordHistory(
									caseRecordUuid, 
									Constants.CaseRecordEventType.COOPERATING_PARTY_MOVED_AS_DEFENDANT, 
									personSigned,
									court.getUuid(), "");
							mf.getSession().saveOrUpdate(pp);				
						}
					}
				}
			}
				
			mf.addCaseRecordHistory(caseRecordUuid, Constants.CaseRecordEventType.FILING_CREATED_BY_LEGAL_PREPARER, personSigned,court.getUuid(), "");
			cr.getFiler().add(personSigned);
			
			newFile.delete();
		}else{
			throw new UploadPackageException("Package or Case is not valid!");
		}
		
	}
	
		private static void splitPDFPackage(DocumentPackage documentPackage, File newFile,
				String caseRecordUuid, Person personSigned, ModelFacade mf, Court c) throws UploadPackageException, IOException {
			
			//HibernatePhaseListener.getSessionFactory().getCurrentSession()
			// .getTransaction().begin();
			DocumentStatus ds = new DocumentStatus();
			ds = mf.findDocumentStatus(6);

			// Pull List of Documents and Page Ranges from DB
			List<DocPageRange> dprList = mf.findAllPageRangeByPackageUuid(documentPackage);

			/*
			 * Check the document for dynamically set page range indicators.
			 * 
			 * If present, over ride page ranges from the database. If not present,
			 * then leave list of documents and page ranges unchanged.
			 */
			PageRangesFromTextTargetsUtility targetBasedRangeChecker = new PageRangesFromTextTargetsUtility();

			/*
			 * TODO Check memory requirements of files and potentially change from
			 * file based passing to in memory objects
			 */
			// Convert file to Byte Array
			// FileInputStream fis = convertFileToInputStream(newFile);
			FileInputStream fis = FileUtility.convertFileToInputStream(newFile);

			List<DocPageRange> dprUpdatedList = targetBasedRangeChecker
					.pageRangesFromTargetsCheck(fis, dprList);
			for (DocPageRange dpr : dprUpdatedList) {
				Hibernate.initialize(
						dpr.getDocumentInstance()
						);
			}
			
			PDDocument pd = PDDocument.load(newFile);
			
			int pageCount = pd.getNumberOfPages();
			int dprPageCount = 0;
			
			// Find the max pageRangeEnd in the DocPageRange list
			for(DocPageRange dn : dprUpdatedList)
			{
				if(dprPageCount < dn.getPageRangeEnd())
				{
					dprPageCount = dn.getPageRangeEnd();
				}
			}
			
			if(pageCount != dprPageCount)
			{
				throw new UploadPackageException("Uploaded document has " + pageCount + " number of pages but" +
						" GAJE expects " + dprPageCount + " pages");
			}
			
			
			SplitPDF sp = new SplitPDF();

			ByteArrayOutputStream[] baosArray = sp.SplitFile("C:" + File.separator + "temp" + File.separator
					+ newFile.getName(), dprUpdatedList);
			// sp.SplitFile( fis, dprUpdatedList);
			int i = 0;

			for (DocPageRange dn : dprUpdatedList) { // Commented out PDFList
				Documents tempDoc = new Documents();
				
				DocumentInstance docInstance = new DocumentInstance();
				docInstance = dn.getDocumentInstance();

				// String fileTitle =
				// (dn.getDocumentInstance().getDescription().toString().replace('
				// ', '_').replace('-','_').replace(':', '_').replace('\'','+'));
				String fileTitle = (dn.getDocumentInstance().getDescription()
						.toString().replace(' ', '_').replace("-", "_").replace(
								",_", "_").replace(':', '_').replace('\'', '_'));

				tempDoc.setTitle(fileTitle);
				tempDoc.setPhysicalType("pdf");
				CaseRecord cr = mf.findCaseRecordById(
						caseRecordUuid, c.getUuid());
				tempDoc.setCaseRecord(cr);
				tempDoc.setDocumentInstance(docInstance);
				tempDoc.setPerson(personSigned);
				tempDoc.setReceivedDateTime(DateUtil.getCurrentDate());
				tempDoc.setStatus(ds);
				
				mf.makePersistent(tempDoc);

				byte[] docContent = baosArray[i].toByteArray();
				tempDoc.setContent(null,docContent);

				List<Documents> listOfDoc = new ArrayList<Documents>();
				listOfDoc = mf.findDocumentsByCaseUuid(
						caseRecordUuid);
								
				for (Documents d : listOfDoc) {
					/*
					 * if
					 * (d.getDocumentInstance().getDocumentType().getCode().equals(
					 * tempDoc.getDocumentInstance().getDocumentType() .getCode())) {
					 * this.getModelFacade().deleteDocument(d); }
					 */

					if (d.getDocumentInstance().getCode() == (tempDoc
							.getDocumentInstance().getCode())
							&& d.getStatus().getCode() == 6 &&
							!d.getUuid().equalsIgnoreCase(tempDoc.getUuid())) {
						mf.deleteDocument(d);
					}
				}
				// file.delete();
				
				i++;
			}
			 //HibernatePhaseListener.getSessionFactory().getCurrentSession()
			 //.getTransaction().commit();
		}
		
		
	/*
	 *  Exhibits are packages made for scanning in variable length documents and
	 *  appending them to the end of an existing document.
	 */
	public static void concatExhibits(DocumentPackage docPackage, File newFile,
			List<Documents> docList, Court court) throws Exception {
		Concatenate concatenate = new Concatenate();
		
		//This is for Bibb county Efiling Court
		
		if (court.getUuid().toString().equalsIgnoreCase("courtUuidBibb")) {
			// append PDF exhibit package to existing PDF documents

			// dpUuid14 ="FormCEJ-EX Review - Modification Petition Exhibits"
			if (docPackage.getUuid().equalsIgnoreCase("dpBibbUuid14")) {
				for (Documents docToAppend : docList) {
					// 174 =
					// "Petition__Adopt_Agency_Recommendation___FormCEJ___Bibb"
					if (docToAppend.getDocumentInstance().getCode() == 174) {
						concatenate.concatenateHelper(docToAppend, newFile
								.getAbsolutePath());
						FacesContext facesContext = FacesContext
								.getCurrentInstance();
						facesContext.addMessage("uploadPackageForm:uploadPack",
								new FacesMessage(" Package has been appened"));
					}
				}
			}
			// "FormCAG-EX - Motion To Redirect Exibits" =dpUuid18
			if (docPackage.getUuid().equalsIgnoreCase("dpBibbUuid18")) {
				for (Documents docToAppend : docList) {
					// Motion to Redirect
					if (docToAppend.getDocumentInstance().getCode() == 179) {
						// "Petition__Adopt_Agency_Recommendation___FormCEJ___Bibb"
						// = 179
						concatenate.concatenateHelper(docToAppend, newFile
								.getAbsolutePath());
						FacesContext facesContext = FacesContext
								.getCurrentInstance();
						facesContext.addMessage("uploadPackageForm:uploadPack",
								new FacesMessage(" Package has been appened"));
					}
				}
			}
			// "FormCAH-EX - Motion To Transfer Exibits" = dpUuid19
			if (docPackage.getUuid().equalsIgnoreCase("dpBibbUuid19")) {
				for (Documents docToAppend : docList) {
					// Motion to Transfer with Attached Order = 41
					if (docToAppend.getDocumentInstance().getCode() == 41) {
						concatenate.concatenateHelper(docToAppend, newFile
								.getAbsolutePath());
						FacesContext facesContext = FacesContext
								.getCurrentInstance();
						facesContext.addMessage("uploadPackageForm:uploadPack",
								new FacesMessage(" Package has been appened"));
					}
				}
			}
			// "FormCCU-EX - Notice of Registration Exibits" = dpUuid20
			if (docPackage.getUuid().equalsIgnoreCase("dpBibbUuid20")) {
				for (Documents docToAppend : docList) {
					// "Notice: Of Registration" =182
					if (docToAppend.getDocumentInstance().getCode() == 182) {
						concatenate.concatenateHelper(docToAppend, newFile
								.getAbsolutePath());
						FacesContext facesContext = FacesContext
								.getCurrentInstance();
						facesContext.addMessage("uploadPackageForm:uploadPack",
								new FacesMessage(" Package has been appened"));
					}
				}
			}
		} else if (court.getUuid().toString().equalsIgnoreCase("courtUuid2")) {
			// Form CEJ-EX Rev/Mod Exhibits = dpUuid21
			if (docPackage.getUuid().equalsIgnoreCase("dpUuid21")) {
				for (Documents docToAppend : docList) {
					// Petition to Adopt Agency Recommendation- CEJ = 135
					if (docToAppend.getDocumentInstance().getCode() == 135) {
						concatenate.concatenateHelper(docToAppend, newFile
								.getAbsolutePath());
						FacesContext facesContext = FacesContext
								.getCurrentInstance();
						facesContext.addMessage("uploadPackageForm:uploadPack",
								new FacesMessage(" Package has been appened"));
					}
				}
			}
			// FormCCP-EX - Petition for Additional Children Exhibits = dpUuid23
			if (docPackage.getUuid().equalsIgnoreCase("dpUuid23")) {
				for (Documents docToAppend : docList) {
					// Petition to Adopt Agency Recommendation - CEJ = 98
					if (docToAppend.getDocumentInstance().getCode() == 98) {
						concatenate.concatenateHelper(docToAppend, newFile
								.getAbsolutePath());
						FacesContext facesContext = FacesContext
								.getCurrentInstance();
						facesContext.addMessage("uploadPackageForm:uploadPack",
								new FacesMessage(" Package has been appened"));
					}
				}
			}
			// FormCAB-EX Motion Contempt Exhibits = dpUuid24
			if (docPackage.getUuid().equalsIgnoreCase("dpUuid24")) {
				for (Documents docToAppend : docList) {
					// Petition to Adopt Agency Recommendation - CEJ = 114
					if (docToAppend.getDocumentInstance().getCode() == 114) {
						concatenate.concatenateHelper(docToAppend, newFile
								.getAbsolutePath());

						FacesContext facesContext = FacesContext
								.getCurrentInstance();
						facesContext.addMessage("uploadPackageForm:uploadPack",
								new FacesMessage(" Package has been appened"));
					}
				}
			}
			// FormCAA-EX Motion Contempt Exhibits = dpUuid5a
			if (docPackage.getUuid().equalsIgnoreCase("dpUuid5a")) {
				for (Documents docToAppend : docList) {
					// Motion For Contempt = 48
					if (docToAppend.getDocumentInstance().getCode() == 48) {
						concatenate.concatenateHelper(docToAppend, newFile
								.getAbsolutePath());

						FacesContext facesContext = FacesContext
								.getCurrentInstance();
						facesContext.addMessage("uploadPackageForm:uploadPack",
								new FacesMessage(" Package has been appended"));
					}
				}
			}

		} else if (court.getUuid().toString().equalsIgnoreCase("courtUuid3")) {

		} else if (court.getUuid().toString().equalsIgnoreCase("courtUuid4")) {

		} else if (court.getUuid().toString().equalsIgnoreCase("courtUuidHart")) {

		} else if (court.getUuid().toString().equalsIgnoreCase("courtUuidJefferson")) {

		} else if(court.getUuid().toString().equalsIgnoreCase("courtUuid5")) {
		
		}else{
			
		}
	}
}